package cn.yunbamboos.mybatis.metadata;

import cn.hutool.core.collection.CollectionUtil;
import cn.yunbamboos.mybatis.Constants;
import cn.yunbamboos.mybatis.metadata.where.TableWhere;
import org.apache.ibatis.mapping.ParameterMap;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.session.Configuration;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 数据库表反射信息
 */
public class TableInfo implements Constants {

    private final Configuration configuration;
    private Class<?> mapperType;
    private Class<?> entityType;
    /**
     * 表名称
     */
    private String tableName;
    /**
     * 表主键信息列表
     */
    private List<TablePrimaryKeyInfo> primaryKeyList;
    /**
     * 表字段信息列表
     */
    private List<TableFieldInfo> fieldList;
    /**
     * 表排序信息列表
     */
    private List<TableOrderInfo> orderList;
    /**
     * 支持列表查询列
     */
    private List<TableWhere> whereList;

    private String resultMap;
    private String parameterMap;

    public TableInfo(Configuration configuration) {
        this.configuration = configuration;
    }

    /**
     * 自动构建 resultMap 并注入
     */
    void initResultMapIfNeed() {
        String id = entityType.getName() + DOT;
        String resultMapId = id + "ResultMap";
        String parameterMapId = id + "ParameterMap";

        List<ResultMapping> resultMappings = new ArrayList<>();
        List<ParameterMapping> parameterMappings = new ArrayList<>();

        // 添加主键
        if (CollectionUtil.isNotEmpty(primaryKeyList)) {
            primaryKeyList.forEach(pk -> {
                resultMappings.add(pk.getResultMapping(configuration));
                parameterMappings.add(pk.getParameterMapping(configuration, resultMapId));
            });
        }
        if (CollectionUtil.isNotEmpty(fieldList)) {
            fieldList.forEach(field -> {
                resultMappings.add(field.getResultMapping(configuration));
                parameterMappings.add(field.getParameterMapping(configuration, resultMapId));
            });
        }
        ResultMap resultMap = new ResultMap.Builder(configuration, resultMapId, entityType, resultMappings).build();
        configuration.addResultMap(resultMap);
        this.resultMap = resultMapId;


        ParameterMap parameterMap = new ParameterMap.Builder(configuration, parameterMapId, entityType, parameterMappings).build();
        configuration.addParameterMap(parameterMap);
        this.parameterMap = parameterMapId;
    }

    public Class<?> getMapperType() {
        return mapperType;
    }

    public void setMapperType(Class<?> mapperType) {
        this.mapperType = mapperType;
    }

    public Class<?> getEntityType() {
        return entityType;
    }

    public void setEntityType(Class<?> entityType) {
        this.entityType = entityType;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public List<TablePrimaryKeyInfo> getPrimaryKeyList() {
        return CollectionUtil.isEmpty(this.primaryKeyList) ? Collections.emptyList() : this.primaryKeyList;
    }

    public void setPrimaryKeyList(List<TablePrimaryKeyInfo> primaryKeyList) {
        this.primaryKeyList = primaryKeyList;
    }

    public List<TableFieldInfo> getFieldList() {
        return CollectionUtil.isEmpty(this.fieldList) ? Collections.emptyList() : this.fieldList;
    }

    public void setFieldList(List<TableFieldInfo> fieldList) {
        this.fieldList = fieldList;
    }

    public List<TableOrderInfo> getOrderList() {
        return CollectionUtil.isEmpty(this.orderList) ? Collections.emptyList() : this.orderList;
    }

    public void setOrderList(List<TableOrderInfo> orderList) {
        this.orderList = orderList;
    }

    public List<TableWhere> getWhereList() {
        return CollectionUtil.isEmpty(this.whereList) ? Collections.emptyList() : this.whereList;
    }

    public void setWhereList(List<TableWhere> whereList) {
        this.whereList = whereList;
    }

    public String getResultMap() {
        return resultMap;
    }

    public String getParameterMap() {
        return parameterMap;
    }
}
